﻿using Library.Common.Common;
using Library.Common.Model;
using Library.Common.Serialize;
using Library.Core.Application;
using Library.Core.Application.BaseAction;
using Library.Core.Application.IInfrastructure;
using Library.Core.Application.IInfrastructure.EntityFrameworkDataAccess;
using Synthesize.BaseSet.Domain.Aggregation.Entity.Authority;
using Synthesize.BaseSet.Domain.DomainService.Authority;
using Synthesize.BaseSet.Domain.Repository.Authority;
using Synthesize.BaseSet.Domain.Specifications.Authority.Menu;
using Synthesize.BaseSet.ServiceInterface.Dtos.Authority.Menu;
using Synthesize.BaseSet.ServiceInterface.UseCase.Authority;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Synthesize.BaseSet.Application.UseCase.Authority
{
    /// <summary>
    /// 菜单信息操作类
    /// </summary>
    public class MenuService : BaseService, IMenuService
    {
        private readonly ITransaction _transaction;
        private readonly IMenuRepository _menuRepository;
        private readonly MenuMoveDomainService _moveMenuDomainservice;
        private readonly IMenuPermissionRepository _menuPermissionRepository;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="container"></param>
        /// <param name="transaction"></param>
        /// <param name="menuRepository"></param>
        /// <param name="moveMenuDomainservice"></param>
        /// <param name="menuPermissionRepository"></param>
        public MenuService(IIocContainer container
            , ITransaction transaction
            , IMenuRepository menuRepository
            , MenuMoveDomainService moveMenuDomainservice
            , IMenuPermissionRepository menuPermissionRepository
            ) : base(container)
        {
            _transaction = transaction;
            _menuRepository = menuRepository;
            _moveMenuDomainservice = moveMenuDomainservice;
            _menuPermissionRepository = menuPermissionRepository;
        }

        /// <summary>
        /// 移动菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<bool>> MoveMenu(MoveMenuInput input)
        {
            return await HandleAsync(input, async () =>
            {
                using (var tran = _transaction.BeginTransactionEF())
                {
                    var result = false;

                    //移动菜单
                    await _moveMenuDomainservice.MoveMenu(input.Platform, input.Id, input.Flag);

                    result = await _menuRepository.SaveAsync();
                    await tran.CommitAsync();

                    return result;
                }
            });
        }

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<bool>> Create(CreateMenuInput input)
        {
            return await HandleAsync(input, async () =>
            {
                var menus = await _menuRepository.GetManyAsync(x => true);
                var sort = 1.0;
                if (menus.Any())
                {
                    sort = menus.Max(x => x.Sort) + 1;
                }
                var menuInfo = MapperHelper<CreateMenuInput, MenuInfoEntity>.Map(input);
                menuInfo.Id = GuidHelper.GetSecuentialGuid();
                menuInfo.Sort = sort;
                //创建判断
                await new CreateMenuSpecification(_menuRepository).SatisfiedBy(menuInfo);
                _menuRepository.Add(menuInfo);

                //需要添加权限
                if (input.MenuPermissionList.Any())
                {
                    var needAddList = new List<MenuPermissionInfoEntity>();
                    foreach (var itemMenuPermission in input.MenuPermissionList)
                    {
                        needAddList.Add(new MenuPermissionInfoEntity()
                        {
                            Id = GuidHelper.GetSecuentialGuid(),
                            MenuId = menuInfo.Id,
                            Code = itemMenuPermission.Code,
                            Name = itemMenuPermission.Name,
                        });
                    }
                    foreach (var item in needAddList)
                    {
                        //操作权限添加判断
                        await new CreateMenuPermissionSpecification(_menuPermissionRepository).SatisfiedBy(item);
                    }
                    if (needAddList.Any())
                    {
                        await _menuPermissionRepository.AddRangeAsync(needAddList);
                    }
                }

                return await _menuRepository.SaveAsync();
            });
        }

        /// <summary>
        /// 显示或隐藏菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<bool>> ForbidOrEnable(ForbidOrEnableInput input)
        {

            return await HandleAsync(input, async () =>
            {
                var menuInfo = await _menuRepository.GetAsync(x => x.Id == input.Id);
                if (menuInfo == null)
                {
                    throw new ApplicationsException("无对应菜单信息！");
                }

                menuInfo.Hidden = !menuInfo.Hidden;
                _menuRepository.Update(menuInfo);

                return await _menuRepository.SaveAsync();
            });
        }

        /// <summary>
        /// 更新菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<bool>> Update(UpdateMenuInput input)
        {
            return await HandleAsync(input, async () =>
            {
                //更新菜单判断
                var menuInfo = MapperHelper<UpdateMenuInput, MenuInfoEntity>.Map(input);
                await new UpdateMenuSpecification(_menuRepository).SatisfiedBy(menuInfo);
                _menuRepository.Update(menuInfo);

                //修改操作权限信息
                var needUpdateList = new List<MenuPermissionInfoEntity>();
                var needAddList = new List<MenuPermissionInfoEntity>();
                var needDeleteList = new List<MenuPermissionInfoEntity>();

                var menuPermissions = await _menuPermissionRepository.GetManyAsync(x => x.MenuId == input.Id);
                if (menuPermissions.Any())
                {
                    //需要修改/删除的
                    if (input.MenuPermissionList.Any() && input.MenuPermissionList.Where(x => x.Id.HasValue).Any())
                    {
                        var permissionIds = input.MenuPermissionList.Where(x => x.Id.HasValue).Select(x => x.Id.Value).ToList();

                        //需要修改的
                        needUpdateList = menuPermissions.Where(x => permissionIds.Contains(x.Id)).ToList();
                        foreach (var item in needUpdateList)
                        {
                            var menuPermission = input.MenuPermissionList.FirstOrDefault(x => x.Id == item.Id);
                            item.Name = menuPermission.Name;
                            item.Code = menuPermission.Code;

                            //操作权限更新判断
                            await new UpdateMenuPermissionSpecification(_menuPermissionRepository).SatisfiedBy(item);
                        }
                        _menuPermissionRepository.UpdateRange(needUpdateList);

                        //需要删除
                        needDeleteList = menuPermissions.Where(x => !permissionIds.Contains(x.Id)).ToList();
                        _menuPermissionRepository.UpdateIsDeletedRange(needDeleteList);
                    }

                    //需要添加的
                    if (input.MenuPermissionList.Any() && input.MenuPermissionList.Where(x => !x.Id.HasValue).Any())
                    {
                        needAddList = input.MenuPermissionList.Where(x => !x.Id.HasValue)
                                        .Select(x => new MenuPermissionInfoEntity()
                                        {
                                            Id = GuidHelper.GetSecuentialGuid(),
                                            MenuId = menuInfo.Id,
                                            Name = x.Name,
                                            Code = x.Code
                                        }).ToList();
                        foreach (var item in needAddList)
                        {
                            //操作权限添加判断
                            await new CreateMenuPermissionSpecification(_menuPermissionRepository).SatisfiedBy(item);
                        }
                        await _menuPermissionRepository.AddRangeAsync(needAddList);
                    }
                }
                else
                {
                    if (input.MenuPermissionList.Any())
                    {
                        //需要添加
                        foreach (var itemMenuPermission in input.MenuPermissionList)
                        {
                            needAddList.Add(new MenuPermissionInfoEntity()
                            {
                                Id = GuidHelper.GetSecuentialGuid(),
                                MenuId = input.Id,
                                Code = itemMenuPermission.Code,
                                Name = itemMenuPermission.Name,
                            });
                        }
                        foreach (var item in needAddList)
                        {
                            //操作权限添加判断
                            await new CreateMenuPermissionSpecification(_menuPermissionRepository).SatisfiedBy(item);
                        }
                        await _menuPermissionRepository.AddRangeAsync(needAddList);
                    }
                }

                return await _menuRepository.SaveAsync();
            });
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<bool>> DeleteById(SingleDeleteInput input)
        {

            return await HandleAsync(input, async () =>
            {
                var menuInfo = await _menuRepository.GetAsync(input.Id);
                if (menuInfo == null)
                {
                    throw new ApplicationsException("无对应菜单信息存在！");
                }
                await new DeleteMenuSpecification(_menuRepository).SatisfiedBy(menuInfo);
                _menuRepository.UpdateIsDeleted(menuInfo);

                //删除对应的权限
                var menuPermissions = await _menuPermissionRepository.GetManyAsync(x => x.MenuId == menuInfo.Id);
                _menuPermissionRepository.UpdateIsDeletedRange(menuPermissions);

                return await _menuRepository.SaveAsync();
            });
        }
    }
}
